package com.password.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

/**
 * DES加密工具
 * 
 * @author yzh
 * @date 2020年5月27日
 *
 */
public class DesUtil {

	/**
	 * DES(Data Encryption Standard)是一种对称加密算法，所谓对称加密就是加密和解密都是使用同一个密钥。
	 */
	// 固定8位的偏移变量
	private final static String DES = "DES";
	private final static String ENCODE = "UTF-8";

	public static byte[] randGenerateDESKey() {
		byte[] randByte = new byte[8]; // 8位des密码长度
		Random random = new Random();
		random.nextBytes(randByte);
		return randByte;
	}

	/**
	 * 使用 默认key 加密
	 * 
	 * @return String
	 * @author lifq
	 * @date 2015-3-17 下午02:46:43
	 */
	public static String encrypt(String data, byte[] key, String dataEncode) throws Exception {
		byte[] bt = encrypt(data.getBytes(dataEncode), key);
		String strs = Base64.getEncoder().encodeToString(bt);
		return strs;
	}

	/**
	 * 使用 默认key 解密
	 * 
	 * @return String
	 * @author lifq
	 * @date 2015-3-17 下午02:49:52
	 */
	public static String decrypt(String data, byte[] key, String dataEncode) throws IOException, Exception {
		if (data == null)
			return null;
		byte[] buf = Base64.getDecoder().decode(data);
		byte[] bt = decrypt(buf, key);
		return new String(bt, dataEncode);
	}

	/**
	 * Description 根据键值进行加密
	 * 
	 * @param data
	 * @param key  加密键byte数组
	 * @return
	 * @throws Exception
	 */
	public static String encrypt(String data, String key) throws Exception {
		byte[] bt = encrypt(data.getBytes(ENCODE), key.getBytes(ENCODE));
		String strs = Base64.getEncoder().encodeToString(bt);
		return strs;
	}

	/**
	 * Description 根据键值进行解密
	 * 
	 * @param data
	 * @param key  加密键byte数组
	 * @return
	 * @throws IOException
	 * @throws Exception
	 */
	public static String decrypt(String data, String key) throws IOException, Exception {
		if (data == null)
			return null;
		byte[] buf = Base64.getDecoder().decode(data);
		byte[] bt = decrypt(buf, key.getBytes(ENCODE));
		return new String(bt, ENCODE);
	}

	/**
	 * Description 根据键值进行加密
	 * 
	 * @param data
	 * @param key  加密键byte数组
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
		// 生成一个可信任的随机数源
		SecureRandom sr = new SecureRandom();
		// 从原始密钥数据创建DESKeySpec对象
		DESKeySpec dks = new DESKeySpec(key);
		// 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
		SecretKey securekey = keyFactory.generateSecret(dks);
		// Cipher对象实际完成加密操作
		Cipher cipher = Cipher.getInstance(DES);
		// 用密钥初始化Cipher对象
		cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
		return cipher.doFinal(data);
	}

	/**
	 * Description 根据键值进行解密
	 * 
	 * @param data
	 * @param key  加密键byte数组
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
		// 生成一个可信任的随机数源
		SecureRandom sr = new SecureRandom();
		// 从原始密钥数据创建DESKeySpec对象
		DESKeySpec dks = new DESKeySpec(key);
		// 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
		SecretKey securekey = keyFactory.generateSecret(dks);
		// Cipher对象实际完成解密操作
		Cipher cipher = Cipher.getInstance(DES);
		// 用密钥初始化Cipher对象
		cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
		return cipher.doFinal(data);
	}

	/**
	 * 获取输入流
	 * @author yzh
	 * @date 2020年5月28日
	 *  
	 * @param in
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static InputStream getDESInputStream(InputStream in, byte[] key) throws Exception {
		// 生成一个可信任的随机数源
		SecureRandom sr = new SecureRandom();
		// 从原始密钥数据创建DESKeySpec对象
		DESKeySpec dks = new DESKeySpec(key);
		// 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
		SecretKey securekey = keyFactory.generateSecret(dks);
		// Cipher对象实际完成解密操作
		Cipher cipher = Cipher.getInstance(DES);
		// 用密钥初始化Cipher对象
		cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
		return new CipherInputStream(in, cipher);
	}

	/**
	 * 获取DES输出流
	 * @author yzh
	 * @date 2020年5月28日
	 *  
	 * @param in
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static OutputStream getDESOutputStream(OutputStream out, byte[] key) throws Exception {
		// 生成一个可信任的随机数源
		SecureRandom sr = new SecureRandom();
		// 从原始密钥数据创建DESKeySpec对象
		DESKeySpec dks = new DESKeySpec(key);
		// 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
		SecretKey securekey = keyFactory.generateSecret(dks);
		// Cipher对象实际完成解密操作
		Cipher cipher = Cipher.getInstance(DES);
		// 用密钥初始化Cipher对象
		cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
		return new CipherOutputStream(out, cipher);
	}

}